'use strict';
const BaseService = require('./base');
const ResponseUtil = require('../utils/ResponseUtil');
const StringUtil = require('../utils/StringUtil');
const HelperUtil = require('../utils/HelperUtil');
const RCEM = require('../utils/ResultCodeEnumMsg');
const VRCE = require('../utils/ViewResultCodeEnum');
const Constant = require('../config/Constant');

class ProductService extends BaseService {


    splitInstallments(total, periods) {
        // 转成最小单位（分）
        const totalCents = Math.round(total * 100)
        const base = Math.floor(totalCents / periods)
        const remainder = totalCents - base * periods

        const result = Array(periods).fill(base)
        for (let i = 0; i < remainder; i++) {
            result[i] += 1
        }

        // 再转换回元
        return result.map((cents) => cents / 100)
    }

    generateMonthlySchedule(data, deductionDateType, deductionDateValue) {
        const result = [];
        const today = new Date();

        for (let i = 0; i < data.length; i++) {
            let date = new Date(today);

            if (deductionDateType === '10') {
                // 下单顺延
                date.setMonth(date.getMonth() + i); // 每期加 i 个月
                date.setDate(date.getDate() + deductionDateValue); // 顺延天数
            } else if (deductionDateType === '20') {
                // 每月固定日，从下个月开始
                date.setMonth(date.getMonth() + 1 + i); // 从下个月开始，每期加 i 个月
                date.setDate(deductionDateValue); // 固定日
                // 处理月份天数不足的情况
                while (date.getMonth() !== (today.getMonth() + 1 + i) % 12) {
                    date.setDate(date.getDate() - 1);
                }
            } else {
                throw new Error('未知 deductionDateType');
            }

            result.push({
                price: data[i].toFixed(2),
                date: date.toISOString().split('T')[0],
            });
        }

        return result;
    }

    async addProduct(body) {
        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        if (!body.title || !body.price || !body.payType)
            return ResponseUtil.resError('参数错误');
        if (!tenantId) {
            return ResponseUtil.resError('未管理租户，请联系管理员');
        }

        let installmentDMap = {};
        for (let i = 0; i < body.installmentArr.length; i++) {
            let d = this.splitInstallments(body.price, Number(body.installmentArr[i]));
            installmentDMap[body.installmentArr[i]] = d;
        }

        for (let key in installmentDMap) {
            let data = installmentDMap[key];
            let newData = this.generateMonthlySchedule(data, body['deductionDateType'], body['deductionDateValue']);
            installmentDMap[key] = newData;
        }


        let productParams = {
            id: StringUtil.getUUIDV2(),
            product_no: await this.ctx.genGoodsNo(),
            tenant_id: tenantId,
            title: body.title,
            subtitle_titile: body.subtitleTitile,
            price: body.price,
            original_price: body.originalPrice,
            order_price_edit: body.orderPriceEdit,
            pay_type: body.payType,
            dedit_flag: body.deditFlag,
            dedit_price_rate: body.deditPriceRate,
            contract_template: body.contractTemplate,
            deduction_date_type: body.deductionDateType,
            deduction_date_value: body.deductionDateValue,
            installment_arr: JSON.stringify(body.installmentArr),
            installment_price_arr: JSON.stringify(installmentDMap),
            image_head: body.imageHead,
            image_detail: body.imageDetail,
            status: body.status || 0,
            sort: body.sort,
            remark: body.remark,
            create_by: createBy,
            create_by_id: operatorId,
            del_flag: 0,
            training_period: body.trainingPeriod,
            teaching_method: body.teachingMethod
        };

        await this.executeInsert('t_product', productParams);

        return productParams.id;
    }


    async selectProductById(productId) {
        let sql = 'select * from t_product where id=? ';
        let result = await this.executeSqlFirst(sql, [productId]);
        if (result) {
            let d = result.installmentArr;
            try {
                result.installmentArr = JSON.parse(d);
            } catch (e) {
                result.installmentArr = [];
            }
        }
        return result;
    }

    async editProduct(body) {
        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        if (!body.title || !body.price || !body.payType || !body.id)
            return ResponseUtil.resError('参数错误');
        if (!tenantId) {
            return ResponseUtil.resError('未管理租户，请联系管理员');
        }

        let installmentDMap = {};
        for (let i = 0; i < body.installmentArr.length; i++) {
            let d = this.splitInstallments(body.price, Number(body.installmentArr[i]));
            installmentDMap[body.installmentArr[i]] = d;
        }

        for (let key in installmentDMap) {
            let data = installmentDMap[key];
            let newData = this.generateMonthlySchedule(data, body['deductionDateType'], body['deductionDateValue']);
            installmentDMap[key] = newData;
        }

        const product = await this.selectProductById(body.id);
        if (!product) {
            return ResponseUtil.resError('未找到产品');
        }

        if (product.tenantId != tenantId) {
            return ResponseUtil.resError(RCEM.NO_PERMISSION[1], RCEM.NO_PERMISSION[0]);
        }

        let productParams = {
            id: body.id,
            tenant_id: tenantId,
            title: body.title,
            subtitle_titile: body.subtitleTitile,
            price: body.price,
            original_price: body.originalPrice,
            order_price_edit: body.orderPriceEdit,
            pay_type: body.payType,
            dedit_flag: body.deditFlag,
            dedit_price_rate: body.deditPriceRate,
            contract_template: body.contractTemplate,
            deduction_date_type: body.deductionDateType,
            deduction_date_value: body.deductionDateValue,
            installment_arr: JSON.stringify(body.installmentArr),
            installment_price_arr: JSON.stringify(installmentDMap),
            image_head: body.imageHead,
            image_detail: body.imageDetail,
            status: body.status || 0,
            sort: body.sort,
            remark: body.remark,
            create_by: createBy,
            create_by_id: operatorId,
            del_flag: 0,
            training_period: body.trainingPeriod,
            teaching_method: body.teachingMethod
        };

        await this.executeUpdate('t_product', productParams);

        return productParams.id;
    }


    async getProductList({keyword, payType, pageNum, pageSize, status}) {
        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        let sql = 'select SQL_CALC_FOUND_ROWS * from t_product where del_flag=0 and tenant_id=? ';


        let wheres = [
            {column: 'title', value: keyword, options: {condition: 'like'}},
            {column: 'pay_type', value: payType},
            {column: 'status', value: status}
        ];

        let formatSqlResult = this.formatSqlWhere(sql, wheres);

        sql = formatSqlResult[0];

        sql += " order by create_time desc ";
        sql = this.addMysqlPageSize(sql, pageNum, pageSize);
        let result = await this.queryPageData(sql, [tenantId].concat(formatSqlResult[1]));

        return result;
    }


    async deleteProduct(productId) {
        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        if (!tenantId) {
            return ResponseUtil.resError('未管理租户，请联系管理员');
        }

        const product = await this.selectProductById(productId);
        if (!product) {
            return ResponseUtil.resError('未找到产品');
        }

        if (product.tenantId != tenantId) {
            return ResponseUtil.resError(RCEM.NO_PERMISSION[1], RCEM.NO_PERMISSION[0]);
        }

        let sql = 'update t_product set del_flag=1 where id = ?';
        return await this.executeSqlSucc(sql, [productId]);
    }

    async updateProductStatus({id, status}) {
        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        if (![0, 1].includes(status)) {
            return ResponseUtil.resError('参数错误');
        }

        if (!tenantId) {
            return ResponseUtil.resError('未管理租户，请联系管理员');
        }

        const product = await this.selectProductById(id);
        if (!product) {
            return ResponseUtil.resError('未找到产品');
        }

        if (product.tenantId != tenantId) {
            return ResponseUtil.resError(RCEM.NO_PERMISSION[1], RCEM.NO_PERMISSION[0]);
        }

        let sql = 'update t_product set status=? where id = ?';
        return await this.executeSqlSucc(sql, [status, id]);
    }


    async getProductApplyList() {
        let {keyword, importantLevel, status, pageNum, pageSize} = this.ctx.query;

        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        let sql = `SELECT SQL_CALC_FOUND_ROWS a.*,b.name as username,b.phone,b.user_no from t_product_apply a INNER JOIN t_user b where a.user_id = b.id `;


        let wheres = [
            {column: 'tenant_id', value: tenantId, options: {tname: 'a'}},
            {column: 'important_level', value: importantLevel, options: {tname: 'a'}},
            {column: 'status', value: status, options: {tname: 'a'}},
        ];

        let formatSqlResult = this.formatSqlWhere(sql, wheres);

        sql = formatSqlResult[0];

        let options = formatSqlResult[1];

        if (keyword) {
            sql += ` AND (u.order_id like "%"?"%" or a.product_no like "%"?"%" or a.product_name like "%"?"%" or b.user_no like "%"?"%" or b.phone like "%"?"%" or b.name like "%"?"%" ) `;
            options.push(keyword);
            options.push(keyword);
            options.push(keyword);
            options.push(keyword);
            options.push(keyword);
            options.push(keyword);
        }


        sql += " order by a.create_time desc ";
        sql = this.addMysqlPageSize(sql, pageNum, pageSize);


        console.log(sql)

        let result = await this.queryPageData(sql, options);

        let list = result.list;
        list.map(function (item) {
            try{
                item.installmentPrice = JSON.parse(item.installmentPrice);
            }catch (e) {
                item.installmentPrice = [];
            }
        })

        return result;
    }

    async updateProductApplyImportantLevel() {
        let loginUserInfo = this.ctx.getLoginInfo();
        let operatorType = loginUserInfo.operatorType;
        let operatorId = loginUserInfo.operatorId;
        let createBy = loginUserInfo.createBy;
        let tenantId = loginUserInfo.tenantId;

        let {remark, importantLevel, id} = this.ctx.request.body;

        if (!id) {
            return ResponseUtil.resError('参数错误');
        }
        if (![1, 2, 3, 4, 5].includes(importantLevel)) {
            return ResponseUtil.resError('参数错误');
        }
        let sql = 'select * from t_product_apply where id = ?';
        let apply = await this.executeSqlFirst(sql, [id]);
        if (!apply) {
            return ResponseUtil.resError('未找到报名信息');
        }

        if (apply.tenantId != tenantId) {
            return ResponseUtil.resError(RCEM.NO_PERMISSION[1], RCEM.NO_PERMISSION[0]);
        }

        sql = 'update t_product_apply set important_level=?,remark=?,update_by=?,update_by_id=? where id=?';
        return await this.executeSqlSucc(sql, [importantLevel, remark, createBy, operatorId, id]);
    }


}

module.exports = ProductService;
